from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.options.common.base import AppiumOptions
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import subprocess
import time
import os


class ThunderAutomator:
    def __init__(self):
        self.driver = None
        self.wait = None

    def start_emulator(self, emulator_index=0):
        """启动雷电模拟器"""
        print("🚀 启动雷电模拟器...")
        ld_path = r"D:\Tools\雷电模拟器\LDPlayer9\ldconsole.exe"

        if os.path.exists(ld_path):
            result = subprocess.run(f'"{ld_path}" launch --index {emulator_index}',
                                    shell=True, capture_output=True, text=True)
            if result.returncode == 0:
                print("✅ 启动命令执行成功")
            else:
                print(f"⚠️ 启动命令返回: {result.stderr}")

        # 等待模拟器启动
        return self.wait_for_adb()

    def wait_for_adb(self, timeout=60):
        """等待ADB设备连接"""
        print("🔍 检查ADB连接...")
        start_time = time.time()

        while time.time() - start_time < timeout:
            try:
                result = subprocess.run(['adb', 'devices'], capture_output=True, text=True, timeout=10)
                if 'emulator-5554' in result.stdout and 'device' in result.stdout:
                    print("✅ ADB连接成功")
                    # 额外等待设备完全启动
                    time.sleep(5)
                    return True
            except subprocess.TimeoutExpired:
                print("⚠️ ADB命令超时，重试...")
            except Exception as e:
                print(f"⚠️ ADB检查异常: {e}")

            print("⏳ 等待设备连接...")
            time.sleep(5)

        print("❌ ADB连接超时")
        return False

    def connect_appium(self):
        """连接Appium服务器"""
        print("🔗 连接Appium服务器...")

        capabilities = {
            'platformName': 'Android',
            'platformVersion': '9',
            'deviceName': 'emulator-5554',
            'automationName': 'UiAutomator2',
            'noReset': True,
            'newCommandTimeout': 300,
        }

        options = AppiumOptions()
        for key, value in capabilities.items():
            options.set_capability(key, value)

        # 尝试连接
        appium_urls = ['http://127.0.0.1:4723', 'http://127.0.0.1:4723/wd/hub']

        for url in appium_urls:
            try:
                print(f"🔄 尝试连接: {url}")
                self.driver = webdriver.Remote(url, options=options)
                self.wait = WebDriverWait(self.driver, 10)
                print(f"✅ Appium连接成功: {url}")
                return True
            except Exception as e:
                print(f"❌ {url} 连接失败: {e}")
                continue

        print("❌ 所有连接尝试都失败")
        return False

    def get_device_info(self):
        """获取设备信息"""
        if not self.driver:
            return

        print("\n📊 设备信息:")
        try:
            print(f"设备品牌: {self.driver.capabilities.get('deviceManufacturer', 'Unknown')}")
            print(f"设备型号: {self.driver.capabilities.get('deviceModel', 'Unknown')}")
            print(f"系统版本: {self.driver.capabilities.get('platformVersion', 'Unknown')}")
            print(f"屏幕分辨率: {self.driver.get_window_size()}")
            print(f"当前包名: {self.driver.current_package}")
            print(f"当前Activity: {self.driver.current_activity}")
        except Exception as e:
            print(f"⚠️ 获取部分设备信息失败: {e}")

    def click_element(self, by, value, desc="", timeout=10):
        """点击元素"""
        if not self.driver:
            print("❌ 未连接到Appium")
            return False

        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable((by, value))
            )
            element.click()
            print(f"✅ 点击: {desc}")
            return True
        except Exception as e:
            print(f"❌ 点击失败 {desc}: {e}")
            return False

    def click_by_class(self, class_name, index=0, desc="", timeout=10):
        """通过类名点击元素"""
        if not self.driver:
            return False

        try:
            elements = WebDriverWait(self.driver, timeout).until(
                lambda driver: driver.find_elements(AppiumBy.CLASS_NAME, class_name)
            )
            if elements and len(elements) > index:
                elements[index].click()
                print(f"✅ 点击: {desc}")
                return True
            else:
                print(f"❌ 未找到元素: {desc} (找到 {len(elements)} 个元素)")
                return False
        except Exception as e:
            print(f"❌ 点击失败 {desc}: {e}")
            return False

    def find_element_by_scrolling(self, target_text, max_scrolls=10):
        """通过滚动查找包含特定文本的元素"""
        found_elements = []
        scroll_count = 0

        while scroll_count < max_scrolls:
            print(f"🔍 第 {scroll_count + 1} 次查找 '{target_text}'...")

            # 查找当前页面所有包含目标文本的元素
            try:
                elements = self.driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR,
                                                     f'new UiSelector().text("{target_text}")')

                for element in elements:
                    if element.is_displayed():
                        element_info = {
                            'element': element,
                            'text': element.text,
                            'location': element.location
                        }
                        if not any(e['text'] == element.text for e in found_elements):
                            found_elements.append(element_info)
                            print(f"✅ 找到: {element.text}")

            except Exception as e:
                print(f"❌ 查找元素失败: {e}")

            # 如果找到了元素，返回第一个
            if found_elements:
                return found_elements[0]['element']

            # 向下滚动
            if not self.scroll_down():
                print("❌ 无法继续滚动")
                break

            scroll_count += 1
            time.sleep(2)

        print(f"❌ 滚动 {max_scrolls} 次后未找到: {target_text}")
        return None

    def scroll_down(self, scroll_amount=0.7):
        """向下滚动页面"""
        try:
            window_size = self.driver.get_window_size()
            start_x = window_size['width'] * 0.5
            start_y = window_size['height'] * 0.7  # 从70%位置开始
            end_y = window_size['height'] * 0.3  # 滚动到30%位置

            self.driver.swipe(start_x, start_y, start_x, end_y, 500)
            print("⬇️ 向下滚动")
            time.sleep(1)  # 等待滚动完成
            return True

        except Exception as e:
            print(f"❌ 滚动失败: {e}")
            return False

    def find_container_with_text_precise(self, target_text, max_scrolls=10):
        """精确查找包含特定文本的容器"""
        scroll_count = 0

        while scroll_count < max_scrolls:
            print(f"🔄 第 {scroll_count + 1} 次精确搜索 '{target_text}'...")

            # 方法1：直接使用UIAutomator查找包含目标文本的容器
            try:
                containers = self.driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR,
                                                       f'new UiSelector().resourceId("com.uu898.uuhavequality:id/itemCategoryItemRoot").childSelector(new UiSelector().text("{target_text}"))')

                if containers:
                    print(f"✅ 直接找到包含 '{target_text}' 的容器")
                    return containers[0]
            except Exception as e:
                print(f"⚠️ 直接查找失败: {e}")

            # 方法2：遍历0-100个容器实例
            for i in range(100):
                try:
                    container = self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
                                                         f'new UiSelector().resourceId("com.uu898.uuhavequality:id/itemCategoryItemRoot").instance({i})')

                    # 在容器内精确查找目标文本
                    text_elements = container.find_elements(AppiumBy.ANDROID_UIAUTOMATOR,
                                                            f'new UiSelector().text("{target_text}")')

                    if text_elements and text_elements[0].is_displayed():
                        print(f"✅ 在第 {i} 个容器中找到 '{target_text}'")
                        return container

                except Exception:
                    # 如果找不到第i个实例，继续下一个
                    continue

            # 方法3：使用XPath查找
            try:
                containers = self.driver.find_elements(AppiumBy.XPATH,
                                                       f'//android.view.ViewGroup[contains(@resource-id, "itemCategoryItemRoot")]//*[@text="{target_text}"]/..')

                if containers:
                    print(f"✅ 通过XPath找到包含 '{target_text}' 的容器")
                    return containers[0]
            except Exception as e:
                print(f"⚠️ XPath查找失败: {e}")

            # 向下滚动继续查找
            if not self.scroll_down():
                break

            scroll_count += 1
            time.sleep(2)

        print(f"❌ 未找到包含 '{target_text}' 的容器")
        return None

    def find_hanging_item_optimized(self, target_text="挂件", max_scrolls=10):
        """优化查找挂件商品：在容器内查找特定布局中的文本"""
        scroll_count = 0

        while scroll_count < max_scrolls:
            print(f"🔍 第 {scroll_count + 1} 次优化查找 '{target_text}'...")

            # 查找所有商品容器
            containers = self.driver.find_elements(AppiumBy.ID,
                "com.uu898.uuhavequality:id/itemCategoryItemRoot")

            print(f"📦 当前页面找到 {len(containers)} 个商品容器")

            for container_index, container in enumerate(containers):
                try:
                    # 在容器内查找 ll_add_printing 布局
                    printing_layout = container.find_element(AppiumBy.ID,
                        "com.uu898.uuhavequality:id/ll_add_printing")

                    # 在 printing_layout 中查找所有 LinearLayout
                    linear_layouts = printing_layout.find_elements(AppiumBy.CLASS_NAME,
                        "android.widget.LinearLayout")

                    print(f"  📍 容器 {container_index}: 找到 {len(linear_layouts)} 个 LinearLayout")

                    # 在每个 LinearLayout 中查找目标文本
                    for layout_index, layout in enumerate(linear_layouts):
                        try:
                            # 查找包含目标文本的元素
                            text_elements = layout.find_elements(AppiumBy.ANDROID_UIAUTOMATOR,
                                f'new UiSelector().text("{target_text}")')

                            if text_elements:
                                text_element = text_elements[0]
                                if text_element.is_displayed():
                                    print(f"    ✅ 在容器 {container_index} 的 Layout {layout_index} 中找到 '{target_text}'")

                                    # 返回容器和找到的文本元素
                                    return {
                                        'container': container,
                                        'text_element': text_element,
                                        'container_index': container_index,
                                        'layout_index': layout_index
                                    }

                        except Exception as e:
                            print(f"    ⚠️ 检查Layout {layout_index} 失败: {e}")
                            continue

                except Exception as e:
                    # 这个容器没有 ll_add_printing 布局，继续下一个
                    continue

            # 如果当前页面没找到，向下滚动
            if not self.scroll_down():
                print("❌ 无法继续滚动")
                break

            scroll_count += 1
            time.sleep(2)

        print(f"❌ 优化查找未找到 '{target_text}'")
        return None

    def find_and_click_hanging_item_optimized(self):
        """使用优化方法查找并点击挂件商品"""
        print("🎯 开始优化查找挂件商品...")

        result = self.find_hanging_item_optimized("挂件")
        if result:
            try:
                container = result['container']
                text_element = result['text_element']

                print(f"📍 找到挂件在容器 {result['container_index']} 的布局 {result['layout_index']}")

                # 方法1：先尝试点击文本元素本身
                try:
                    if text_element.get_attribute('clickable') == 'true':
                        text_element.click()
                        print("✅ 点击挂件文本成功")
                        return True
                except:
                    pass

                # 方法2：点击容器内的可点击元素
                clickable_items = container.find_elements(AppiumBy.XPATH, './/*[@clickable="true"]')
                if clickable_items:
                    # 优先点击第一个可点击元素
                    clickable_items[0].click()
                    print("✅ 点击挂件容器内的可点击元素成功")
                    return True

                # 方法3：最后点击整个容器
                container.click()
                print("✅ 点击挂件容器成功")
                return True

            except Exception as e:
                print(f"❌ 点击挂件失败: {e}")
                return False

        print("❌ 优化查找未找到挂件商品")
        return False

    def find_and_click_hanging_item(self):
        """查找并点击挂件商品（兼容旧方法）"""
        print("🎯 开始精确查找挂件商品...")

        # 使用精确查找方法
        container = self.find_container_with_text_precise("挂件")
        if container:
            try:
                # 在容器内查找可点击的元素
                clickable_items = container.find_elements(AppiumBy.XPATH, './/*[@clickable="true"]')

                if clickable_items:
                    # 打印可点击元素信息用于调试
                    for i, item in enumerate(clickable_items):
                        try:
                            text = item.text if item.text else "无文本"
                            class_name = item.get_attribute('class')
                            print(f"  📦 可点击元素 {i}: {class_name} - 文本: '{text}'")
                        except:
                            print(f"  📦 可点击元素 {i}: 信息获取失败")

                    # 点击第一个可点击元素
                    clickable_items[0].click()
                    print("✅ 点击挂件商品成功")
                    return True
                else:
                    # 如果没有可点击元素，直接点击容器
                    container.click()
                    print("✅ 点击挂件容器成功")
                    return True

            except Exception as e:
                print(f"❌ 点击挂件失败: {e}")
                return False

        print("❌ 未找到挂件商品")
        return False

    def take_screenshot(self, name=None):
        """截取屏幕截图"""
        if not self.driver:
            return

        try:
            screenshot_dir = "screenshots"
            if not os.path.exists(screenshot_dir):
                os.makedirs(screenshot_dir)

            if name is None:
                name = f"screenshot_{int(time.time())}"

            filename = f"{screenshot_dir}/{name}.png"
            self.driver.save_screenshot(filename)
            print(f"📸 截图已保存: {filename}")
            return filename
        except Exception as e:
            print(f"❌ 截图失败: {e}")
            return None

    def run_automation(self):
        """执行自动化流程"""
        print("=" * 50)
        print("🚀 开始自动化流程")
        print("=" * 50)

        # 启动模拟器
        if not self.start_emulator():
            print("❌ 模拟器启动失败")
            return

        # 连接Appium
        if not self.connect_appium():
            print("❌ Appium连接失败")
            return

        # 显示设备信息
        self.get_device_info()

        # 截取初始屏幕
        self.take_screenshot("start")

        try:
            # 执行操作流程
            operations = [
                (self.click_by_class, ("android.widget.TextView", 2), "软件", 10),
                (self.click_by_class, ("android.widget.TextView", 1), "买商品", 3),
                (self.click_element, (AppiumBy.ID, "com.uu898.uuhavequality:id/filter_iv"), "筛选1", 3),
                (self.click_element, (AppiumBy.ID, "com.uu898.uuhavequality:id/tvManagerLayout"), "应用按钮", 3),
                (self.click_by_class, ("android.view.ViewGroup", 0), "第一个商品", 3),
                (self.find_and_click_hanging_item_optimized, (), "优化查找并点击挂件", 5),  # 使用优化方法
            ]

            for i, (method, args, desc, wait_time) in enumerate(operations, 1):
                print(f"\n📍 步骤 {i}/{len(operations)}: {desc}")

                if method == self.find_and_click_hanging_item_optimized:
                    success = method()
                elif len(args) == 2:
                    success = method(args[0], args[1], desc)
                else:
                    success = method(*args, desc)

                if not success:
                    print(f"⚠️ 步骤 '{desc}' 执行失败，继续后续步骤...")
                    self.take_screenshot(f"step_{i}_failed")

                time.sleep(wait_time)

            print("\n🎉 所有操作完成!")
            self.take_screenshot("completed")

        except Exception as e:
            print(f"💥 自动化流程执行出错: {e}")
            self.take_screenshot("error")
            raise

    def close(self):
        """关闭连接"""
        if self.driver:
            try:
                print("\n🛑 正在关闭连接...")
                self.driver.quit()
                print("✅ 连接已关闭")
            except Exception as e:
                print(f"⚠️ 关闭连接时出现异常: {e}")


def main():
    automator = ThunderAutomator()
    try:
        automator.run_automation()
    except Exception as e:
        print(f"💥 程序执行出错: {e}")
    finally:
        automator.close()
        input("\n按Enter键退出程序...")


if __name__ == "__main__":
    main()